package model.notes.impl;

import model.notes.Note;

public class NoteImpl implements Note {

	private static final NoteValue DEFAULT_NOTE_VALUE = NoteValue.NOIRE;
	
	private NoteName name;
	private NoteAlteration alteration;
	private NoteValue value;
	
	public NoteImpl (NoteName name) {
		this.name = name;
		this.value = DEFAULT_NOTE_VALUE;
		this.alteration = NoteAlteration.NO_ALTERATION;
		
	}
	
	public NoteImpl (NoteName name, NoteValue value) {
		this(name);
		this.value = value;
	}
	
	public NoteImpl (NoteName name, NoteAlteration alteration) {
		this(name);
		this.alteration = alteration;
	}
	
	public NoteImpl (NoteName name, NoteValue value, NoteAlteration alteration) {
		this(name);
		this.value = value;
		this.alteration = alteration;
	}
	
	@Override
	public InternationalNoteName getInternationalName() {
		
		InternationalNoteName result = null;
		
		switch (this.name) {
		case DO:
			result = InternationalNoteName.C;
			break;
		case RE:
			result = InternationalNoteName.D;
			break;
		case MI:
			result = InternationalNoteName.E;
			break;
		case FA:
			result = InternationalNoteName.F;
			break;
		case SOL:
			result = InternationalNoteName.G;
			break;
		case LA:
			result = InternationalNoteName.A;
			break;
		case SI:
			result = InternationalNoteName.B;
			break;
		}
		return result;
	}

	@Override
	public NoteName getName() {
		return this.name;
	}

	public NoteAlteration getAlteration() {
		return alteration;
	}

	public void setAlteration(NoteAlteration alteration) {
		this.alteration = alteration;
	}

	public NoteValue getValue() {
		return value;
	}

	public void setValue(NoteValue value) {
		this.value = value;
	}

	public String toString() {
		return this.name.toString() + this.alteration.toString();
	}

	public double getTonality() {
		return this.name.getTonality() + this.alteration.getTonality();
	}
	
	private static Note getAlteredNote(Note originalNote, double alterationValue) {
		return getAlteredNote(originalNote, alterationValue, true);
	}
	
	private static Note getAlteredNote(Note originalNote, double alterationValue, boolean isDiese) {
		double tonality = originalNote.getTonality() + alterationValue;
		NoteName noteName = NoteName.valueOf(tonality % 6);
		Note note = null;
		if (noteName == null) {
			if (isDiese) {
			noteName = NoteName.valueOf((tonality - 0.5) % 6);
			note = new NoteImpl(noteName, NoteAlteration.DIESE);
			} else {
				noteName = NoteName.valueOf((tonality + 0.5) % 6);
				note = new NoteImpl(noteName, NoteAlteration.BEMOL);
			}
		} else {
			note = new NoteImpl(noteName);
		}
		return note;
	}
	
	@Override
	public Note getTierceMajeure(boolean alterWithDiese) {
		return getAlteredNote(this, 2, alterWithDiese);
	}

	@Override
	public Note getQuarte(boolean alterWithDiese) {
		return getAlteredNote(this, 2.5, alterWithDiese);
	}
	
	@Override
	public Note getQuinteMineure(boolean alterWithDiese) {
		return getAlteredNote(this, 3, alterWithDiese);
	}
	
	@Override
	public Note getQuinteMajeure(boolean alterWithDiese) {
		return getAlteredNote(this, 4, alterWithDiese);
	}

	@Override
	public Note getQuinte(boolean alterWithDiese) {
		return getAlteredNote(this, 3.5, alterWithDiese);
	}


	@Override
	public Note getSecondeMajeure(boolean alterWithDiese) {
		return getAlteredNote(this, 1, alterWithDiese);
	}

	@Override
	public Note getSecondeMineure(boolean alterWithDiese) {
		return getAlteredNote(this, 0.5, alterWithDiese);
	}

	@Override
	public Note getSeptiemeMajeure(boolean alterWithDiese) {
		return getAlteredNote(this, 5.5, alterWithDiese);
	}

	@Override
	public Note getSeptiemeMineure(boolean alterWithDiese) {
		return getAlteredNote(this, 5, alterWithDiese);
	}

	@Override
	public Note getSixte(boolean alterWithDiese) {
		return getAlteredNote(this, 4.5, alterWithDiese);
	}

	@Override
	public Note getTierceMineure(boolean alterWithDiese) {
		return getAlteredNote(this, 1.5, alterWithDiese);
	}

	@Override
	public Note[] getGammeMajeure() {
		Note[] gamme = new Note[7];
		gamme[0] = this;
//		Note secondeMajeure = this.getSecondeMajeure();
//		
//		gammeMajeureText.append(note.getTierceMajeure());
//		gammeMajeureText.append(note.getQuarte());
//		gammeMajeureText.append(note.getQuinte());
//		gammeMajeureText.append(note.getSixte());
//		gammeMajeureText.append(note.getSeptiemeMajeure());
		
		return gamme;
	}

	@Override
	public Note[] getGammeMineure() {
		// TODO Auto-generated method stub
		return null;
	}
	
	
}
